import Bullet from "./bullet.js"
import {calc_distance} from "./utils.js"

class Weapon {
    constructor(game, row, col, config) {
        this.game = game;
        this.row = row;
        this.col = col;

        //{type: 1, bullet_power: 100, bullet_speed: 20, fire_interval: 200, fire_cell_range: 5, fire_range: 0}
        this.config = config;
        this.map_cell = game.map.row_col_2_vector(this.row, this.col);

        let cell_width = game.map.map_info.cell_width;
        let fire_cell_range = config.fire_cell_range;
        // calculate from fire_range and cell_width
        this.config.fire_range = cell_width * fire_cell_range;

        this.bullet_list = [];

        if (!Weapon.hasOwnProperty("weapon_frames")) Weapon.weapon_frames = [this.bg_draw()];

        this.fire_duration = 0;
        this.score = 0;
    }

    set_position(row, col) {
        this.row = row;
        this.col = col;
        this.map_cell = this.game.map.row_col_2_vector(this.row, this.col);
    };

    draw(preview) {
        let map_info = this.game.map.map_info;
        let game = this.game;

        if (!this.map_cell) return;

        let weapon = game.weapon_utils.find_weapon(this.row, this.col);
        if (preview && (weapon || this.map_cell.is_start_end_cell())) {
            this.map_cell.draw_mark("deny");
            return;
        }

        this.frame_index = this.frame_index || 0;
        let frame_len = this.constructor.weapon_frames.length;
        this.frame_index = (this.frame_index + 1) % frame_len;

        let ctx = map_info.ctx_map;
        let start_xy = this.map_cell.get_start_xy();
        let [x, y] = start_xy;

        ctx.drawImage(this.constructor.weapon_frames[this.frame_index], x, y);

        if (preview) this.show_fire_range();
    };

    show_fire_range() {
        if (!this.config.fire_range) return;

        let ctx = this.game.map.map_info.ctx_map;
        let center_xy = this.map_cell.get_center_xy();
        let [x, y] = center_xy;

        ctx.lineWidth = 1;
        ctx.fillStyle = "rgba(100, 100, 100, 0.3)";
        ctx.strokeStyle = "#666";
        ctx.setLineDash([10, 10]);

        ctx.beginPath();
        ctx.arc(x, y, this.config.fire_range, 0, Math.PI * 2, true);
        ctx.fill();
        ctx.stroke();

        ctx.setLineDash([]);
    };

    draw_bullet() {
        let bullet_list = this.bullet_list;
        for (let i = 0; i < bullet_list.length; i++) {
            bullet_list[i].draw();
        }
    };

    bullet_move_on() {
        let bullet_list = this.bullet_list;
        for (let i = 0; i < bullet_list.length; i++) {
            bullet_list[i].move_on();
        }
    };

    bullet_check_hit() {
        let bullet_list = this.bullet_list;
        for (let i = 0; i < bullet_list.length; i++) {
            bullet_list[i].check_hit();
        }
    };

    cls_bullet() {
        let bullet_list = this.bullet_list;
        for (let i = bullet_list.length - 1; i >= 0; i--) {
            let bullet = bullet_list[i];
            if (bullet.is_end()) {
                bullet_list.splice(i, 1);
            }
        }
    };

    calc_fire_pos() {
        let spirit = this.find_spirit();
        if (!spirit) return null;

        let calibrate = spirit.config.fire_calibrate; // 校准
        if (spirit) {
            let spirit_pos = spirit.position;
            let distance = calc_distance(this.map_cell.get_center_xy(), spirit_pos);
            let fire_range = this.config.fire_range;
            let rate = distance / fire_range;
            calibrate = calibrate * rate || 0;

            let [x1, y1] = spirit_pos;
            switch (spirit.move_direct) {
                case 0:
                    y1 -= calibrate;
                    break;
                case 1:
                    x1 += calibrate;
                    break;
                case 2:
                    y1 += calibrate;
                    break;
                case 3:
                    x1 -= calibrate;
            }
            return [x1, y1];
        }
        return null;
    };

    find_spirit(all) {
        let spirit_list = this.game.game_info.spirit_list;
        let weapon = this;
        spirit_list = spirit_list.filter(function (spirit) {
            if (spirit.blood <= 0) return false;
            let spirit_pos = spirit.position;
            let weapon_pos = weapon.map_cell.get_center_xy();
            let xy = calc_distance(spirit_pos, weapon_pos);
            return xy <= weapon.config.fire_range;
        });

        if (all) return spirit_list.length ? spirit_list : null;

        spirit_list.sort(function (a, b) {
            return b.position[0] + b.position[1] - a.position[0] - a.position[1];
        });

        return spirit_list.length ? spirit_list.shift() : null;
    };

    fire() {
        let ts = new Date().getTime();
        if (this.ts && ts - this.ts < this.config.fire_interval) return;

        this.ts = ts;

        let position = this.map_cell.get_center_xy();
        let end_pos = this.calc_fire_pos();
        if (end_pos) {
            this.bullet_list.push(new Bullet(this, position, end_pos, this.config));
            this.fire_duration += this.config.fire_interval;
        }
    };

    bg_draw(frame) {
        let map_info = this.game.map.map_info;
        let {cell_width, cell_height} = map_info;
        frame = frame || 0;

        let bg_ele = document.createElement("canvas");
        bg_ele.width = cell_width;
        bg_ele.height = cell_height;

        let bg_ctx = bg_ele.getContext("2d");
        let x = cell_width / 2;
        let y = cell_height / 2;

        let style_list0 = ["#999999", "#999999", "#999999", "#ff0000", "#999999", "#ffffff", "#ffffff"];
        let style_list1 = ["#ffffff", "#ffffff", "#00ff00", "#ffffff", "#ff0000", "#999999", "#999999"];
        let style_list2 = ["#0000ff", "#ff0000", "#0000ff", "#999999", "#ffffff", "#ff0000", "#ffffff"];

        bg_ctx.fillStyle = style_list0[frame];
        bg_ctx.beginPath();
        bg_ctx.arc(x, y, cell_width / 2, 0, Math.PI * 2, true);
        bg_ctx.fill();

        bg_ctx.fillStyle = style_list1[frame];
        bg_ctx.beginPath();
        bg_ctx.arc(x, y, cell_width / 3, 0, Math.PI * 2, true);
        bg_ctx.fill();

        bg_ctx.fillStyle = style_list2[frame];
        bg_ctx.beginPath();
        bg_ctx.arc(x, y, cell_width / 6, 0, Math.PI * 2, true);
        bg_ctx.fill();
        return bg_ele;
    };
}

export default Weapon;